package com.solomon.travel.common.util;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Map;

import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class EncryptUtil {
	
	private static final String SIGN_METHOD_HMAC = "hmac";
	private static final String SIGN_METHOD_MD5 = "md5";
	
	private static byte[] encryptHMAC(String data, String secret) throws IOException {
		byte[] bytes = null;
		try {
			SecretKey secretKey = new SecretKeySpec(secret.getBytes("UTF-8"), "HmacMD5");
			Mac mac = Mac.getInstance(secretKey.getAlgorithm());
			mac.init(secretKey);
			bytes = mac.doFinal(data.getBytes("UTF-8"));
		} catch (GeneralSecurityException gse) {
			throw new IOException(gse.toString());
		}
		return bytes;
	}
	
	public static String signTopRequest(Map<String, Object> params, String secret, String signMethod) throws IOException {
		// 第一步：检查参数是否已经排序
				String[] keys = params.keySet().toArray(new String[0]);
				Arrays.sort(keys);

				// 第二步：把所有参数名和参数值串在一起
				StringBuilder query = new StringBuilder();
				if (SIGN_METHOD_MD5.equals(signMethod)) {
					query.append(secret);
				}
				for (String key : keys) {
					String value = (String) params.get(key);
					if (areNotEmpty(key, value)) {
						query.append(key).append(value);
					}
				}

				// 第三步：使用MD5/HMAC加密
				byte[] bytes;
				if (SIGN_METHOD_HMAC.equals(signMethod)) {
					bytes = encryptHMAC(query.toString(), secret);
				} else {
					query.append(secret);
					bytes = encryptMD5(query.toString());
				}

				// 第四步：把二进制转化为大写的十六进制
				return byte2hex(bytes);
	}
	
	public static String signToWeixinPay(Map<String, Object> params, String secret, String signMethod) throws IOException {
				// 第一步：检查参数是否已经排序
				String[] keys = params.keySet().toArray(new String[0]);
				Arrays.sort(keys);

				// 第二步：把所有参数名和参数值串在一起
				StringBuilder query = new StringBuilder();
				
				for (String key : keys) {
					String value = (String) params.get(key);
					if (areNotEmpty(key, value)) {
						query.append(key+"=").append(value);
					}
				}

				// 第三步：使用MD5/HMAC加密
				query.append("key="+secret);
				return IdUtils.MD5(query.toString());
	}

	private static byte[] encryptMD5(String data) throws IOException {
		return encryptMD5(data.getBytes("UTF-8"));
	}

	/**
	 * 对字节流进行MD5摘要。
	 */
	private static byte[] encryptMD5(byte[] data) throws IOException {
		byte[] bytes = null;
		try {
			MessageDigest md = MessageDigest.getInstance("MD5");
			bytes = md.digest(data);
		} catch (GeneralSecurityException gse) {
			throw new IOException(gse.toString());
		}
		return bytes;
	}

	private static  String byte2hex(byte[] bytes) {
		StringBuilder sign = new StringBuilder();
		for (int i = 0; i < bytes.length; i++) {
			String hex = Integer.toHexString(bytes[i] & 0xFF);
			if (hex.length() == 1) {
				sign.append("0");
			}
			sign.append(hex.toUpperCase());
		}
		return sign.toString();
	}

	/**
	 * 检查指定的字符串列表是否不为空。
	 */
	private static  boolean areNotEmpty(String... values) {
		boolean result = true;
		if (values == null || values.length == 0) {
			result = false;
		} else {
			for (String value : values) {
				result &= !isEmpty(value);
			}
		}
		return result;
	}

	/**
	 * 检查指定的字符串是否为空。
	 * <ul>
	 * <li>SysUtils.isEmpty(null) = true</li>
	 * <li>SysUtils.isEmpty("") = true</li>
	 * <li>SysUtils.isEmpty("   ") = true</li>
	 * <li>SysUtils.isEmpty("abc") = false</li>
	 * </ul>
	 *
	 * @param value 待检查的字符串
	 * @return true/false
	 */
	private static boolean isEmpty(String value) {
		int strLen;
		if (value == null || (strLen = value.length()) == 0) {
			return true;
		}
		for (int i = 0; i < strLen; i++) {
			if ((Character.isWhitespace(value.charAt(i)) == false)) {
				return false;
			}
		}
		return true;
	}
	
	
	public static String getSha1(String str){
        if(str==null||str.length()==0){
            return null;
        }
        char hexDigits[] = {'0','1','2','3','4','5','6','7','8','9',
                'a','b','c','d','e','f'};
        try {
            MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
            mdTemp.update(str.getBytes("UTF-8"));

            byte[] md = mdTemp.digest();
            int j = md.length;
            char buf[] = new char[j*2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
                buf[k++] = hexDigits[byte0 & 0xf];      
            }
            return new String(buf);
        } catch (Exception e) {
            // TODO: handle exception
            return null;
        }
    }
}
